#PosDtarget: Target Displacement in positive direction corresponding to $dof. 
#NegDtarget: Target Displacement in negative direction corresponding to $dof.  
#CycNum: Number of times in one cyclic loading.
#Dincr: Displacement increment.
#nodeTag: Integer tag identifying node.
#dof: Integer tag identifying node.
#tol: The tolerance criteria used to check for convergence.
proc Cyclic_Proc { PosDtarget NegDtarget CycNum Dincr nodeTag dof tol {ele_tag 0} {sec_tag 0} {strainlimit 0} } {
	#Define Method
	constraints Transformation
	numberer RCM
	system UmfPack
	test NormDispIncr $tol 50
	algorithm KrylovNewton
	analysis Static
	#Excced Strain Limit or not
	set is_exceed_limit "false"
	#Multi-Cycling-Number
	for {set ii 1} {$ii <=$CycNum} {incr ii} {
		#Define forward Laoding
		set ok [Push_Analysis_Proc $PosDtarget $Dincr $nodeTag $dof]
		#Check Analysis State
		if {$ok != 0} {
			return -1
		}
		#Monitor ELEMENT Exists
		if { $ele_tag != 0 } {
			set is_exceed_limit [is_Reach_Limit $strainlimit -$strainlimit "false" $ele_tag $sec_tag]
		}
		#Define backward Laoding
		set ok [Push_Analysis_Proc [expr $NegDtarget - $PosDtarget] -$Dincr $nodeTag $dof]
		#Check Analysis State
		if {$ok != 0} {
			return -1
		}
		#Monitor ELEMENT Exists
		if { $ele_tag != 0 } {
			set is_exceed_limit [is_Reach_Limit $strainlimit -$strainlimit "false" $ele_tag $sec_tag]
		}
		#Define forward Laoding
		set ok [Push_Analysis_Proc [expr -1 * $NegDtarget] $Dincr $nodeTag $dof]
		#Check Analysis State
		if {$ok != 0 || $is_exceed_limit} {
			return -1
		}
	}
	return 0
}


#Displacement: Displacment to Impose
#Dincr: Displacement increment in each step.
#Node: Node which applied displacment.
#dof: Direction of cyclic loading.
proc Push_Analysis_Proc { Displacement Dincr Node dof } {
	#Step_Number
	set Step_Num [expr int($Displacement / $Dincr)]
	#Define Displacement Loading
	integrator DisplacementControl $Node $dof $Dincr;
	#Loading
	for {set step 1} {$step <=$Step_Num} {incr step} {
		set ok [Analyze_SingleStep_Proc]
		#Convergence Failure
		if {$ok != 0} {
			return -1
		}
	}
	#Finish
	return 0
}

#dt: Time-step increment. Required if transient or variable transient analysis
proc Analyze_SingleStep_Proc { {dt "" } } {
	set ok [analyze 1 $dt]
	if { $ok == 0 } {
		return 0
	} 
	puts "Try KrylovNewton."
	test NormDispIncr 0.1 200
	algorithm  KrylovNewton 
	set ok [analyze 1 $dt]
	if { $ok == 0 } {
		test NormDispIncr 0.05 50
		algorithm NewtonLineSearch 0.75
		return 0
	} 
	puts "Try Relative Test."
	test RelativeNormDispIncr 0.1 200
	algorithm NewtonLineSearch 0.75
	set ok [analyze 1 $dt]
	if { $ok == 0 } {
		test NormDispIncr 0.05 50
		algorithm NewtonLineSearch 0.75
		return 0
	} 
	puts "Try Relative Test and KrylovNewton."
	test RelativeNormDispIncr 0.1 200
	algorithm  KrylovNewton 
	set ok [analyze 1 $dt]
	if { $ok == 0 } {
		test NormDispIncr 0.05 50
		algorithm NewtonLineSearch 0.75
		return 0
	} 
	puts "Try Broyden."
	algorithm Broyden 200
	test NormDispIncr 0.1 200
	set ok [analyze 1 $dt]
	if { $ok == 0 } {
		test NormDispIncr 0.05 50
		algorithm NewtonLineSearch 0.75
		return 0
	} 
	puts "Convergence Failure!"
	return -1
}

#step: Step Number to Impose Gravity Load
proc Gravity_Proc { numIncr } {
	set incr [expr 1./$numIncr]	
	constraints Transformation
	numberer RCM
	system UmfPack
	test EnergyIncr 1.0e-6 200
	integrator LoadControl $incr
	algorithm Newton
	analysis Static
	analyze $numIncr
	puts "Gravity Done."
	loadConst -time 0.0
}



#loadTag: Integer tag identifying the load case.
#nodeTag: Integer tag identifying the node.
#dof: Degree of freedom at the node.
#incr: Load increment.
#YieldStrain: Yield strain.
#ele_tag: Integer tag identifying element.
#sec_tag: Integer tag identifying section. Default is 0 for zero-length element.
proc Get_Yeild_Disp { loadTag nodeTag dof incr YieldStrain ele_tag {sec_tag 0} } {
	#Define Horizontal Force
	pattern Plain $loadTag Linear {
		if { $dof == 1 } {
			load $nodeTag $incr 0 0 0 0 0
		} else {
			load $nodeTag 0 $incr 0 0 0 0
		}
	}
	#Define Analysis Multiplier
	set Multiplier 0
	##While Steel Bar Yield Then Stop Analysis
	while {(![is_Reach_Limit $YieldStrain -$YieldStrain "false" $ele_tag $sec_tag])} {
		##Push by One Step
        set ok [analyze 1]
		##If Analysis Fail then break
		if { $ok != 0 } {
			break
		} 
		incr Multiplier
    }
	##Getting the Disp of Node
	set YieldDisp [nodeDisp $nodeTag $dof]
	##LoadConst 
	loadConst -time 0.0
	##If No Load Added
	if { $Multiplier == 0 } {
		return -1
	}
	##New LoadTag
	incr loadTag
	##Unloading LoadCase
	pattern Plain $loadTag Linear {
    	if { $dof == 1 } {
			load $nodeTag [expr -1 * $incr] 0 0 0 0 0
		} else {
			load $nodeTag [expr -1 * $incr] 0 0 0 0
		}
	}
	##Unloading
	analyze $Multiplier
	##LoadConst 
	loadConst -time 0.0
	##Retrun 
	set YieldDisp [format "%.2f" $YieldDisp]
	return $YieldDisp
}




